
local ft = require 'bindings.freetype6'
local alien = require 'alien'
local imageio = require 'imageio'
local screen = require 'guac.screen'
local config = require 'config'
local setmetatable, error, print, type, tonumber
    = setmetatable, error, print, type, tonumber
local strbyte
    = string.byte


module (...)


local dpi = tonumber(config.text_dpi) or 72

local boxed_ptr = alien.buffer(alien.sizeof('pointer'))

local init_error = ft.Init_FreeType(boxed_ptr)
if (init_error ~= 0) then
  error("unable to initialize FreeType")
end

local lib = boxed_ptr:get(1, 'pointer')

local font_proto = {}
local font_meta = {__index = font_proto}

function loadfont(path, sz)
  local load_error = ft.New_Face(lib, path, 0, boxed_ptr)
  if (load_error ~= 0) then
    return nil
  end
  local face = boxed_ptr:get(1, 'pointer')
  ft.Set_Char_Size(face, 0, 64*sz, dpi, dpi)
  local face_struct = ft.FaceRec:new(face)
  local slot = face_struct.glyph
  local slot_struct = ft.GlyphSlotRec:new(slot)
  return setmetatable({face = face, slot = slot, face_struct = face_struct, slot_struct = slot_struct}, font_meta)
end

function font_proto:render(str)
  local face, slot = self.face, self.slot
  local slot_struct = self.slot_struct
  local charcode = strbyte(str)
  local glyph_i = ft.Get_Char_Index(face, charcode)
  ft.Load_Glyph(face, glyph_i, ft.LOAD_DEFAULT)
  ft.Render_Glyph(slot, ft.RENDER_MODE_NORMAL)
  local w, h, pitch = slot_struct.bitmap_width, slot_struct.bitmap_rows, slot_struct.bitmap_pitch
  local text_pixmap = imageio.createpixmap(w, h, pitch, 'p8', imageio.grays)
  alien.memcpy(text_pixmap.buffer, slot_struct.bitmap_buffer, pitch * h)
  text_pixmap = text_pixmap:changeformat('r8g8b8a8')
  return screen.loadImage(text_pixmap)
end
